package com.torry.workflow.common.exception.handler;

import com.torry.workflow.common.base.result.Result;
import com.torry.workflow.common.exception.BizException;

import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;

/**
 * 全局异常拦截
 *
 * @author wtao
 * @date 2021-10-28 14:22
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 自定义异常
     *
     * @param e exception
     * @return ExceptionResult
     * @author wtao
     * @date 2021/10/30 16:50
     */
    @ExceptionHandler(BizException.class)
    public Result error(BizException e) {
        log.info("【统一异常处理】拦截到异常 {}: {}", e.getClass(), e.getMsg());
        //e.printStackTrace();
        return Result.fail(e.getCode(), e.getMsg());
    }

    /**
     * 这个方法 主要为了 拦截 Response401 中的getWriter() has already been called for this response 异常
     *
     * @param e IllegalStateException
     * @author wtao
     * @date 2021/10/30 16:50
     */
    @ExceptionHandler(IllegalStateException.class)
    public void error(IllegalStateException e) {
        // 拦截异常，不做任何操作
    }

    /**
     * 参数校验异常
     *
     * @param e 异常
     * @return ExceptionResult
     * @author wtao
     * @date 2021/10/30 16:35
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result error(MethodArgumentNotValidException e) {
        e.printStackTrace();
        String msg = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();

        log.info("【统一异常处理】拦截到异常 {}: {}", e.getClass(), e.getMessage());

        return Result.fail(msg);
    }


    /**
     * 参数校验异常
     *
     * @param e 异常
     * @return ExceptionResult
     * @author wtao
     * @date 2021/10/30 16:35
     */
    @ExceptionHandler(BindException.class)
    public Result illegalStateException(BindException e) {
        e.printStackTrace();
        return Result.fail(validation(e.getBindingResult()));
    }


    /**
     * 参数绑定异常
     *
     * @param e exception
     * @return ExceptionResult
     * @author wtao
     * @date 2021/10/30 16:51
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public Result error(HttpMessageNotReadableException e) {
        e.printStackTrace();
        log.info("【统一异常处理】拦截到异常 {}: {}", e.getClass(), e.getMessage());
        return Result.fail("参数异常，请检查参数类型是否匹配");
    }


    /**
     * 数据库插入异常
     *
     * @param e 异常
     * @return Result Result
     * @author torry
     * @date 2021/10/14 16:36
     */
    @ExceptionHandler(DuplicateKeyException.class)
    public Result error(DuplicateKeyException e) {
        e.printStackTrace();
        log.info("【统一异常处理】拦截到异常 {}: {}", e.getClass(), e.getMessage());
        return Result.fail("保存失败，可能已经存在重复数据");
    }


    private String validation(BindingResult bindingResult) {

        List<ObjectError> errors = bindingResult.getAllErrors();

        StringBuilder sb = new StringBuilder();

        if (!CollectionUtils.isEmpty(errors)) {

            for (ObjectError error : errors) {

                FieldError fieldError = (FieldError) error;
                sb.append(fieldError.getDefaultMessage() + ",");
            }
        }

        return sb.length() > 0 ? sb.substring(0, sb.length() - 1) : sb.toString();
    }

}
